/**
 * 错误数据收集器
 * 负责收集和翻译各种错误信息
 */

import type {
  JavaScriptErrorInfo,
  NetworkErrorInfo,
  VueErrorInfo,
} from '~/types/monitor';

export class ErrorCollector {
  /**
   * 错误信息中英文对照表
   */
  private static readonly ERROR_TRANSLATIONS: Record<string, string> = {
    // JavaScript基础错误类型
    ReferenceError: '引用错误',
    TypeError: '类型错误',
    SyntaxError: '语法错误',
    RangeError: '范围错误',
    URIError: 'URI错误',
    EvalError: 'Eval错误',
    InternalError: '内部错误',

    // 常见错误描述
    'is not defined': '未定义',
    'Cannot read property': '无法读取属性',
    'Cannot read properties of null': '无法读取null的属性',
    'Cannot read properties of undefined': '无法读取undefined的属性',
    'Cannot set property': '无法设置属性',
    'is not a function': '不是一个函数',
    'is not a constructor': '不是一个构造函数',
    'Cannot access before initialization': '在初始化之前无法访问',

    // 语法相关错误
    'Unexpected token': '意外的标记',
    'Unexpected end of input': '意外的输入结束',
    'Invalid or unexpected token': '无效或意外的标记',
    'Missing catch or finally after try': '缺少catch或finally语句',
    'Illegal return statement': '非法的return语句',
    'Identifier has already been declared': '标识符已经被声明',
    'Duplicate parameter name not allowed': '不允许重复的参数名',
    'Invalid left-hand side in assignment': '赋值语句左侧无效',

    // 运行时错误
    'Maximum call stack size exceeded': '超出最大调用栈大小（可能是无限递归）',
    'out of range': '超出范围',
    'Invalid array length': '无效的数组长度',
    'Cannot convert undefined or null to object':
      '无法将undefined或null转换为对象',

    // 网络和资源错误
    'JSON.parse': 'JSON解析错误',
    fetch: '网络请求错误',
    XMLHttpRequest: 'Ajax请求错误',
    'Script error': '脚本错误（可能是跨域问题）',
    'Network Error': '网络错误',
    'Failed to fetch': '获取资源失败',
    'Load failed': '资源加载失败',
    'Permission denied': '权限被拒绝',
    'Access denied': '访问被拒绝',
    'Cross-Origin': '跨域错误',
    CORS: '跨域资源共享错误',
    timeout: '请求超时',
    abort: '请求中止',
    cancelled: '请求已取消',
  };

  /**
   * 网络错误状态码中文对照表
   */
  private static readonly HTTP_STATUS_TRANSLATIONS: Record<number, string> = {
    400: '请求参数错误',
    401: '未授权访问',
    403: '访问被禁止',
    404: '请求的资源不存在',
    405: '请求方法不被允许',
    408: '请求超时',
    409: '请求冲突',
    410: '请求的资源已被删除',
    413: '请求实体过大',
    414: '请求URI过长',
    415: '不支持的媒体类型',
    429: '请求过于频繁',
    500: '服务器内部错误',
    501: '服务器不支持该功能',
    502: '网关错误',
    503: '服务暂时不可用',
    504: '网关超时',
    505: 'HTTP版本不受支持',
  };

  /**
   * 翻译错误信息
   */
  static translateErrorMessage(englishMessage: string): string {
    let chineseMessage = englishMessage;

    for (const [english, chinese] of Object.entries(this.ERROR_TRANSLATIONS)) {
      if (englishMessage.includes(english)) {
        chineseMessage = chineseMessage.replace(
          new RegExp(english, 'gi'),
          chinese
        );
      }
    }

    return chineseMessage;
  }

  /**
   * 翻译网络错误信息
   */
  static translateNetworkError(message: string, status?: number): string {
    // 优先根据状态码翻译
    if (status && this.HTTP_STATUS_TRANSLATIONS[status]) {
      return `${this.HTTP_STATUS_TRANSLATIONS[status]} (${status})`;
    }

    // 根据错误信息翻译
    return this.translateErrorMessage(message);
  }

  /**
   * 收集JavaScript错误信息
   */
  static collectJavaScriptError(
    message: string,
    source?: string,
    line?: number,
    column?: number,
    stack?: string,
    type: JavaScriptErrorInfo['type'] = 'javascript'
  ): JavaScriptErrorInfo {
    return {
      type,
      originalMessage: message,
      chineseMessage: this.translateErrorMessage(message),
      source,
      line,
      column,
      stack,
      timestamp: Date.now(),
    };
  }

  /**
   * 收集网络错误信息
   */
  static collectNetworkError(
    url: string,
    method: string,
    message: string,
    status?: number,
    statusText?: string,
    requestData?: any,
    responseData?: any,
    duration?: number,
    type: NetworkErrorInfo['type'] = 'fetch'
  ): NetworkErrorInfo {
    return {
      type,
      method,
      url,
      status,
      statusText,
      originalMessage: message,
      chineseMessage: this.translateNetworkError(message, status),
      requestData,
      responseData,
      timestamp: Date.now(),
      duration,
    };
  }

  /**
   * 收集Vue错误信息
   */
  static collectVueError(
    message: string,
    component?: string,
    stack?: string
  ): VueErrorInfo {
    return {
      message: this.translateErrorMessage(message),
      component,
      stack,
      timestamp: Date.now(),
    };
  }
}
